package com.bangdao.hu.roomba.Views;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import com.bangdao.hu.R;
import com.bangdao.hu.TestBluetoothActivity;
import com.bangdao.hu.roomba.ConnectedThread;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import static com.bangdao.hu.TestBluetoothActivity.btThread;

public class DriveView extends Activity implements TextToSpeech.OnInitListener {
	private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
	public static final int REQUEST_ENABLE_BT = 0;
	public static final String TAG = "DebugInfo";
	private Button driveForwardButton;
	private Button driveBackwardButton;
	private Button driveLeftButton;
	private Button driveRightButton;
	private Button driveStopButton;
	private Button route1Button;
	private Button route2Button;
	private EditText speedText;
	private EditText noiseText;
	private Button spinButton;
//	private ConnectedThread btThread;
	private double yPos, xPos = 0;
	private float turningRadius = 0;
	
	private double orientation;
	private WifiManager wifi;
	private TextToSpeech tts;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.drive_panel);
		setupViews();
		wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
//        tts = new TextToSpeech(this,this);
//      sayYes();
	}
	// Implements TextToSpeech.OnInitListener.
    public void onInit(int status) {
        // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
        if (status == TextToSpeech.SUCCESS) {
            int result = tts.setLanguage(Locale.US);

            if (result == TextToSpeech.LANG_MISSING_DATA ||
                result == TextToSpeech.LANG_NOT_SUPPORTED) {
               // Lanuage data is missing or the language is not supported.
                Log.e(TAG, "Language is not available.");
            } else {
            	
            }
        } else {
            // Initialization failed.
            Log.e(TAG, "Could not initialize TextToSpeech.");
        }
    }
	
	 @Override
	    protected void onDestroy() {
	    	super.onDestroy();
			 
			 if (tts != null) {
				 tts.stop();
			     tts.shutdown();
			 }
	    }
	
	void setupViews()
	{
		spinButton = (Button)findViewById(R.id.spin_button);
		driveForwardButton = (Button)findViewById(R.id.drive_forward_button);
		driveBackwardButton = (Button)findViewById(R.id.drive_backward_button);
		driveLeftButton = (Button)findViewById(R.id.drive_left_button);
		driveRightButton = (Button)findViewById(R.id.drive_right_button);
		driveStopButton = (Button)findViewById(R.id.drive_stop_button);
		route1Button = (Button)findViewById(R.id.route_button);
		route2Button = (Button)findViewById(R.id.route_button_2);
		speedText = (EditText)findViewById(R.id.speed);
		noiseText = (EditText)findViewById(R.id.turn);
		driveForwardButton.setOnTouchListener(new View.OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				if(btThread == null)
					return false;

                if(event.getAction() == MotionEvent.ACTION_UP){  
                	btThread.stopDrive();
                }   
                if(event.getAction() == MotionEvent.ACTION_DOWN){  
                	btThread.goStraightAt(200); // millimeters 
                }
				
				return false;
			}
		});
		
		driveBackwardButton.setOnClickListener(new View.OnClickListener(){

			public void onClick(View v) {
				btThread.goBackward(500);
            	btThread.stopDrive();
            	yPos=yPos-500;
            	new Thread(new Runnable() {
				    public void run() {
				    	sendWifiSignal();
				    }
				  }).start();
			}

		});
		
		driveForwardButton.setOnClickListener(new View.OnClickListener(){

			public void onClick(View v) {
				btThread.goForward(500);
            	btThread.stopDrive();
            	yPos=yPos+500;
            	new Thread(new Runnable() {
				    public void run() {
				    	sendWifiSignal();
				    }
				  }).start();
			}

		});
		
		route2Button.setOnTouchListener(new View.OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				int speed = Integer.parseInt(speedText.getText().toString());
				int noise = Integer.parseInt(noiseText.getText().toString());
				float pausetime = noise/1000 + (float) Math.abs(((float)(230 * Math.PI / 360.0)) * 103.8 / speed );
				int realpause = (int) (pausetime*1000);
				if(btThread == null)
					return false;
                if(event.getAction() == MotionEvent.ACTION_UP){  
                	btThread.stopDrive();
                }   
                if(event.getAction() == MotionEvent.ACTION_DOWN){
                	btThread.goForward(1000);
                	btThread.stopDrive();
                	btThread.drive(speed,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Third POI
                	btThread.goForward(600);
                	btThread.stopDrive();
                	btThread.drive(speed,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Fourth POI
                	btThread.goForward(1000);
                	btThread.stopDrive();
                	btThread.drive(speed,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Last Point
                	btThread.goForward(600);
                	btThread.stopDrive();
                	btThread.drive(speed,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	/*
                	btThread.goForward(1000);
                	btThread.stopDrive();
                	btThread.spinLeft(90);
                	btThread.goForward(500);
                	btThread.stopDrive();
                	btThread.spinLeft(90);
                	btThread.goForward(1000);
                	btThread.stopDrive();
                	btThread.spinLeft(90);
                	btThread.goForward(500);
                	btThread.stopDrive();
                	btThread.spinLeft(90);
                	*/

                	
                }
				
				return false;
			}
		});
		
		route1Button.setOnTouchListener(new View.OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				float pausetime = (float) Math.abs(((float)(230 * Math.PI / 360.0)) * 103.8 / 200 );
				int realpause = (int) (pausetime*1000);
				if(btThread == null)
					return false;
                if(event.getAction() == MotionEvent.ACTION_UP){  
                	//btThread.stopDrive();
                }   
                if(event.getAction() == MotionEvent.ACTION_DOWN){
                	
//                	MapGenerator newMap = new MapGenerator();
                	/*
                	//First POI
                	btThread.drive(200,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Second POI
                	btThread.goForward(1000);
                	btThread.stopDrive();
                	btThread.drive(200,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Third POI
                	btThread.goForward(500);
                	btThread.stopDrive();
                	btThread.drive(200,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Fourth POI
                	btThread.goForward(1000);
                	btThread.stopDrive();
                	btThread.drive(200,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Last Point
                	btThread.goForward(500);
                	btThread.stopDrive();
                	*/
//                	for(int i = 0; i<10; i++)
//                	{
//                		btThread.goForward(500);
//                		btThread.stopDrive();
//                		new Thread(new Runnable() {
//        				    public void run() {
//        				      
//        				    	sendWifiSignal();
//        				    }
//        				  }).start();
//                	}
                	/*
                	btThread.goForward(1429);
                	btThread.stopDrive();
                	btThread.drive(200,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	btThread.goForward(2000);
                	btThread.stopDrive();
                	btThread.drive(200,-1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	btThread.goForward(12857);
                	btThread.stopDrive();
                	btThread.drive(200,1);
                	btThread.pause(realpause*2);
                	btThread.stopDrive();
                	/*
                	// 35*6m Play - Length 1
                	btThread.goForward(35000);
                	for(int i = 0; i < 35; i++)
                	{
                		btThread.goForward(1000);
                		sendWifiSignal();
                	}
                	btThread.stopDrive();
                	btThread.drive(200,1);
                	btThread.pause(realpause);
                	
                	btThread.stopDrive();
                	//Width 1
                	btThread.goForward(6000);
                	btThread.stopDrive();
                	btThread.drive(200,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Length 2
                	btThread.goForward(35000);
                	btThread.stopDrive();
                	btThread.drive(200,1);
                	btThread.pause(realpause);
                	btThread.stopDrive();
                	//Final Width
                	btThread.goForward(6000);
                	btThread.stopDrive();
                	*/
                	/*
                	HashMap<String, Double> wifiMap = new HashMap<String, Double>();
                	wifiMap.put("dd:34:db:55", -78.9999);
            		wifiMap.put("dd:34:da:55",500 -78.9999);
            		wifiMap.put("dd:34:dd:55", -78.9999);
            		wifiMap.put("dd:34:ec:55", -78.9999);
            		wifiMap.put("dd:34:df:55", -78.9999);
            		double[] currentPos = {0, 5.5};
                	//New Map Point created and added to the Final Map
                	MapPoint mapPt = new MapPoint(currentPos,wifiMap);
                	newMap.putPoint(mapPt);*/
                }
				
				return false;
			}
		});
		
		driveBackwardButton.setOnTouchListener(new View.OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				Toast.makeText(DriveView.this, "backward", Toast.LENGTH_LONG).show();
				if(btThread == null)
					return false;
                if(event.getAction() == MotionEvent.ACTION_UP){  
                	btThread.stopDrive();
                }   
                if(event.getAction() == MotionEvent.ACTION_DOWN){  
                	btThread.goStraightAt(-200); // millimeters 
                }
                return false;
			}
		});
		
		driveLeftButton.setOnTouchListener(new View.OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				if(btThread == null)
					return false;
                if(event.getAction() == MotionEvent.ACTION_UP){  
                	btThread.stopDrive();
                }   
                if(event.getAction() == MotionEvent.ACTION_DOWN){  
                	btThread.turnLeft();
                }
				return false;
			}
		});
		
		driveRightButton.setOnTouchListener(new View.OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				if(btThread == null)
					return false;
                if(event.getAction() == MotionEvent.ACTION_UP){  
                	btThread.stopDrive();
                }   
                if(event.getAction() == MotionEvent.ACTION_DOWN){  
                	btThread.turnRight();
                }
				return false;
			}
		});
		
		
		driveStopButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				Toast.makeText(DriveView.this, "stop", Toast.LENGTH_LONG).show();if(btThread != null)
				{
					btThread.stopDrive();
				}		
			}
		});
		
	}
	
	private void sendWifiSignal()
    {
    	String signal = "";
    	wifi.startScan();
    	List<ScanResult> scanResults = wifi.getScanResults();
    	for(ScanResult sr:scanResults)
        { 
    		Log.i("SignalTag", sr.toString());
    		sendPacket("x: ," + xPos + ", y: ," + yPos + ", " + sr.BSSID + ", " + sr.level);
//    		MapGenerator.getInstance().putPoint(currentPoint)
//    		sendPacket( sr.toString());
        }
  	}
	
	private void sendCords()
    {
		sendPacket("x: ," + xPos + ", y: ," + yPos);
  	}
    
    public void scanRoute(View view){
    	btThread.setSpeed(150);
    	orientation = 0;
    	xPos = 0;
    	yPos = 0;
    	//move(0,14286);
    	//move(0,4286);
    	//move(90,4286);
    	//move(270,31428);
    	btThread.drive(200,1);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();
    
    	btThread.pause(1450);
    	btThread.stopDrive();
    }
    
    public void wifiScan(View view){
    	btThread.setSpeed(150);
    	orientation = 0;
    	xPos = 0;
    	yPos = 0;
    	move(0,14286);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();
    	move(90,4286);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();
    	move(270,31248);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();
    	/*for (int i=0;i<28;i++){
    		move(0,500);
    		new Thread(new Runnable() {
    		    public void run() {
    		    	sendWifiSignal();
    		    }
    		  }).start();
    	}
    	move(0,286);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();
    	for (int i=0;i<8;i++){
    		move(0,500);
    		new Thread(new Runnable() {
    		    public void run() {
    		    	sendWifiSignal();
    		    }
    		  }).start();
    	}
    	move(0,286);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();
    	move(90,100);
    	for (int i=0;i<8;i++){
    		move(0,500);
    		new Thread(new Runnable() {
    		    public void run() {
    		    	sendWifiSignal();
    		    }
    		  }).start();
    	}
    	move(0,186);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();
    	move(270,0);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();
    	for (int i=0;i<62;i++){
    		move(0,500);
    		new Thread(new Runnable() {
    		    public void run() {
    		    	sendWifiSignal();
    		    }
    		  }).start();
    	}
    	move(0,428);
    	new Thread(new Runnable() {
		    public void run() {
		    	sendWifiSignal();
		    }
		  }).start();*/
    }
    
    public void spinCalculation(double degree){
		float pausetime = 100/1000+(float) Math.abs(((float)(230 * Math.PI / 360.0)) * 103.8 / 100 );
		int realpause = (int) (pausetime*1000*degree/90);
		btThread.drive(100,1);
    	btThread.pause(realpause);
    	btThread.stopDrive();
    }
    
    public void spin(View view){
    	orientation = 0;
    	xPos = 0;
    	yPos = 0;
    	for (int i=0;i<12;i++){
    		move(0,500);
    		new Thread(new Runnable() {
    		    public void run() {
    		    	sendWifiSignal();
    		    }
    		  }).start();
    	}
    }
    
    public void move(double turn, double forward)
	{
    	spinCalculation(turn);
    	btThread.goForward((int)forward);
    	btThread.stopDrive();
    	
		orientation += turn;//  + new Random().nextGaussian()*turn_noise;
		orientation %= 360;
		double distance = forward; // + new Random().nextGaussian()*forward_noise;
		xPos = distance * Math.cos(turn/360*2*Math.PI) + xPos;
		yPos = distance * Math.sin(turn/360*2*Math.PI) + yPos;
	}
    
    private void sendPacket(String packet)
    {
    	
    	try {
//    		Toast.makeText(this, "trying", Toast.LENGTH_LONG).show();
			Socket socket = new Socket("138.25.110.94", 12345);
//			Toast.makeText(this, "conncted", Toast.LENGTH_LONG).show();
			PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//			out.println("hello, processing");
			out.println(packet);
			
//			Toast.makeText(this, "writed", Toast.LENGTH_LONG).show();
    	} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
	
	
	
	public void startVoiceRecognition(View view) {
	    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
	    //uses free form text input
	    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
	        RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
	    //Puts a customized message to the prompt
	    startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
	}
	
	 private void sayYes() {
		 tts.speak("Command Accepted",TextToSpeech.QUEUE_FLUSH,null);
	 }
	
	protected void onActivityResult(int requestCode, int resultCode,
            Intent data) {
        if (requestCode == REQUEST_ENABLE_BT) {
            if (resultCode == RESULT_OK) {
                // A contact was picked.  Here we will just display it
                // to the user.
                Toast.makeText(this, "bluetooth ennabled successfully", Toast.LENGTH_LONG).show();
               // showPairedDevices();
            }
        }
        
        if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) {
	        // Fill the list view with the strings the recognizer thought it could have heard
	        ArrayList<String> matches = data.getStringArrayListExtra(
	                RecognizerIntent.EXTRA_RESULTS);
	       
	        String cmd = matches.get(0).toString().trim();
	        if (cmd.equals("left")){
	        	sayYes();
	        	btThread.turnLeft();
	        	btThread.pause(3000);
	        	btThread.stopDrive();
	        }
	        else if (cmd.equals("march"))
	        {
	        	sayYes();
	        	btThread.goForward(1000);
	        	btThread.stopDrive();
	        }
	        else if (cmd.equals("fall back"))
	        {
	        	sayYes();
	        	btThread.goStraightAt(-200);
	        	btThread.pause(3000);
	        	btThread.stopDrive();
	        }
	        else if (cmd.equals("right"))
	        {
	        	sayYes();
	        	btThread.turnRight();
	        	btThread.pause(3000);
	        	btThread.stopDrive();
	        }
	        else if (cmd.equals("spin left"))
	        {
	        	sayYes();
	        	btThread.spinLeft(90);
	        	btThread.stopDrive();
	        }
	        else if (cmd.equals("spin right"))
	        {
	        	sayYes();
	        	btThread.spinRight(90);
	        	btThread.stopDrive();
	        }
	        Toast.makeText(this, cmd, Toast.LENGTH_LONG).show();

    }
	}

}

